﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SharpSoft.WPF.Controls
{
    using System.Windows;
    using System.Windows.Controls;
    using Gma.QrCodeNet.Encoding;
    /// <summary>
    /// 用于呈现二维码
    /// </summary>
    public class QrCodeControl : Control
    {
        static QrCodeControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(QrCodeControl), new FrameworkPropertyMetadata(typeof(QrCodeControl)));
        }
        public QrCodeControl()
        {

        }

        private BitMatrix matrix;


        /// <summary>
        /// 要显示的内容
        /// </summary>
        public string Content
        {
            get { return (string)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }

        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register("Content", typeof(string), typeof(QrCodeControl), new PropertyMetadata("QRCODE", new PropertyChangedCallback((dobj, dpc) =>
            {
                if (dobj is QrCodeControl qcc)
                {
                    qcc.ReQrCode();
                }
            })));
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == BackgroundProperty || e.Property == ForegroundProperty || e.Property == BorderBrushProperty || e.Property == BorderThicknessProperty)
            {
                this.InvalidateVisual();
            }
            else if (e.Property == ErrorCorrectionLevelProperty)
            {
                this.ReQrCode();
            }
        }



        public ErrorCorrectionLevel ErrorCorrectionLevel
        {
            get { return (ErrorCorrectionLevel)GetValue(ErrorCorrectionLevelProperty); }
            set { SetValue(ErrorCorrectionLevelProperty, value); }
        }

        public static readonly DependencyProperty ErrorCorrectionLevelProperty =
            DependencyProperty.Register("ErrorCorrectionLevel", typeof(ErrorCorrectionLevel), typeof(QrCodeControl), new PropertyMetadata(ErrorCorrectionLevel.M));



        protected void ReQrCode()
        {
            Gma.QrCodeNet.Encoding.QrEncoder encoder = new Gma.QrCodeNet.Encoding.QrEncoder();
            encoder.ErrorCorrectionLevel = this.ErrorCorrectionLevel;
            var success = encoder.TryEncode(this.Content, out QrCode qrCode);
            if (success && qrCode.isContainMatrix)
            {
                this.matrix = qrCode.Matrix;
            }
            else
            {
                this.matrix = null;
            }
            this.ReRender();
        }

        private void ReRender()
        {
            if (this.matrix != null)
            {
                PathGeometry path = new PathGeometry();
                var uw = this.RenderSize.Width / this.matrix.Width;
                var uh = this.RenderSize.Height / this.matrix.Height;
                for (int x = 0; x < this.matrix.Width; x++)
                {
                    for (int y = 0; y < this.matrix.Height; y++)
                    {
                        var bit = this.matrix[x, y];
                        if (bit)
                        {
                            var rect = new Rect(uw * x, uh * y, uw, uh);
                            path.AddGeometry(new RectangleGeometry(rect));
                        }
                    }
                }
                this.pathGeometry = path;
            }
            else
            {
                this.pathGeometry = null;
            }
            this.InvalidateVisual();

        }
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            this.ReRender();
        }

        private PathGeometry pathGeometry;
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);
            dc.DrawRectangle(this.Background, null, new Rect(new Point(), this.RenderSize));
            if (this.matrix != null)
            {
                var brush = this.Foreground;
                dc.DrawGeometry(brush, null, this.pathGeometry);
            }
        }
    }
}
